package cn.pugle.oj.leetcode;

import cn.pugle.oj.catalog.Unknown;

import java.util.*;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * https://leetcode.com/problems/sort-array-by-increasing-frequency/
 * Given an array of integers nums, sort the array in increasing order based on the frequency of the values.
 * If multiple values have the same frequency, sort them in decreasing order.
 * Return the sorted array.
 * Example 1:
 * Input: nums = [1,1,2,2,2,3]
 * Output: [3,1,1,2,2,2]
 * Explanation: '3' has a frequency of 1, '1' has a frequency of 2, and '2' has a frequency of 3.
 * Example 2:
 * Input: nums = [2,3,1,3,2]
 * Output: [1,3,3,2,2]
 * Explanation: '2' and '3' both have a frequency of 2, so they are sorted in decreasing order.
 * Example 3:
 * Input: nums = [-1,1,-6,4,5,-6,1,4,1]
 * Output: [5,-1,4,4,-6,-6,1,1,1]
 * <p>
 * Constraints:
 * <p>
 * 1 <= nums.length <= 100
 * -100 <= nums[i] <= 100
 */
class LC1636  implements Unknown {
    public int[] frequencySort(int[] nums) {
        Map<Integer, Long> collect = Arrays.stream(nums).boxed()
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
        int[] ints = collect.entrySet().stream()
//                .sorted((o1, o2) -> o1.getValue().compareTo(o2.getValue()))
//                .sorted(Comparator.comparing(Map.Entry::getValue))
                .sorted(Map.Entry.<Integer, Long>comparingByValue()
                        .thenComparing(Map.Entry.<Integer, Long>comparingByKey().reversed()))
                .flatMap(new Function<Map.Entry<Integer, Long>, Stream<?>>() {
                    @Override
                    public Stream<?> apply(Map.Entry<Integer, Long> x) {
                        int[] i = new int[Math.toIntExact(x.getValue())];
                        Arrays.fill(i, x.getKey());
                        return Arrays.stream(i).boxed();
                    }
                })
                .mapToInt(value -> ((Integer)value).intValue())
                .toArray();
        return ints;
    }

    public static void main(String[] args) {
        System.out.println(Arrays.toString(new LC1636().frequencySort(new int[]{2,3,1,3,2})));
    }
}